﻿using System;
using System.Collections.Generic;
using CI;
using CI.Interfaces;
using CI.Organism;

namespace Mesopotamia.SystemTests
{
    /// <summary>
    /// Single Organisms with Asexual reproduction
    /// </summary>
    public class SingleOrganismASexualRepoduction : SingleOrganismNoRepoduction
    {
        private readonly SimEnv _simEnv = SimEnv.Instance;

        /// <summary>
        /// Load the organisms out of the database
        /// </summary>
        /// <param name="environment">Environment name to load</param>
        /// <param name="hostEnvironment"></param>
        /// <param name="maxLoadCount"></param>
        /// <param name="selectedOrganismsToLoad"></param>
        /// <returns>Organisms</returns>
        public override IHostingEnvironment LoadHostingEnvironment(string environment, IHostingEnvironment hostEnvironment, int maxLoadCount, List<Guid> selectedOrganismsToLoad)
        {
            _simEnv.TraceLogger.LogDebug("Loading Organisms - Start");

            _organism = new CI.Organism.Organism(hostEnvironment, new Guid(), _AmoebaEnergy, 20);

            _geneCreate = new GeneCellular(_organism, Guid.NewGuid());
            _geneDestory = new GeneCellular(_organism, Guid.NewGuid());
            _geneASexual = new GeneReproductionAsexual(_organism, Guid.NewGuid());

            // add the cell collection
            _organism.Cells = _cells;
            // create dna structure
            _organism.DNA = _dna;
            // setup the chromosome collection
            _organism.DNA.Chromosomes = _chromosomes;
            // add the cellular chromosome
            _chromosomes.Add(_chromosomeCellular);
            // add the reproduction chrosomes
            _chromosomes.Add(_chromosomeReproduction);
            // add a gene collection
            _chromosomeCellular.Genes = _genesCellular;
            // add the reproductive genes to the repoductive chromosome
            _chromosomeReproduction.Genes = _genesReproductive;

            #region Gene to Create childOrganism
            // add a gene to create the childOrganism
            _genesCellular.Add(_geneCreate);
            // tell the gene who the childOrganism is
            _geneCreate.Organism = _organism;
            // add a requirement colleciton to that gene
            _geneCreate.Requirements = _requirementsCreate;
            // create a body to start after the first heart beat
            _requirementBodyCreate = new HBOffsetTime(_organism, 1, ComparisonType.Equal, Guid.NewGuid());
            // add a body as this is the first step
            _requirementsCreate.Add(_requirementBodyCreate);
            // set the action type as adding
            _geneCreate.ActionType = ActionType.AddCell;
            // create the pysical body
            _body = new Amoeba(_organism, Guid.NewGuid());
            // set the gene's cell
            _geneCreate.Cell = _body;
            #endregion

            #region gene to Destory childOrganism
            // add a gene to create the childOrganism
            _genesCellular.Add(_geneDestory);
            // tell the gene who the childOrganism is
            _geneDestory.Organism = _organism;
            // add a requirement colleciton to that gene
            _geneDestory.Requirements = _requirementsDestroy;
            // destroy the body after x heart beat
            _requirementBodyDestory = new HBOffsetTimeCell(_organism, 99, _body, ComparisonType.Equal, Guid.NewGuid());
            // add a body as this is the first step
            _requirementsDestroy.Add(_requirementBodyDestory);
            // set the action type as adding
            _geneDestory.ActionType = ActionType.DelCell;
            // set the gene's cell
            _geneDestory.Cell = _body;
            #endregion

            #region Gene for Reproduction
            // add a ASexual gene
            _genesReproductive.Add(_geneASexual);
            // tell the gene who the childOrganism is
            _geneASexual.Organism = _organism;
            // set the mutation rate at 0%
            _geneASexual.MutationRate = 0;
            // set the requirements list
            _geneASexual.Requirements = _requirementsASexual;
            // add a requirement
            _requirementASexual = new HBOffsetTimeCell(_organism, 3, _body, ComparisonType.Equal, Guid.NewGuid());
            // add the requirement
            _requirementsASexual.Add(_requirementASexual);

            #endregion

            // as we want the childOrganism to grow from dna the nerual system will be empty
            _simEnv.TraceLogger.LogDebug("Set Empty Nerual System");
            _organism.NeuralSystem = null;

            // set alive organisms
            _organisms.AliveAdd(_organism);

            // set the dead organisms
            _organisms.Dead.Clear();

            // tell the childOrganism what environment it belongs to
            _organisms.hostEnvironment = hostEnvironment;

            // tell the childOrganism what group of organisms it belongs to
            _organism.Organisms = _organisms;

            _simEnv.TraceLogger.LogDebug("Loading Organisms - End");

            return hostEnvironment;
        }
    }
}